#include "adaptive_precision.h"

#include <limits>
#include <vector>

#include "adaptive_precision.h"

#include <limits>
#include <vector>

double sum(double a, double b, double & roundoff)
{
	double result = a + b;
	double b_virt = result - a;
	double a_virt = result - b_virt;
	double b_roundoff = b - b_virt;
	double a_roundoff = a - a_virt;
	roundoff = a_roundoff + b_roundoff;
	return result;
}

void split(double a, std::size_t s, double & a_hi, double & a_lo)
{
	double c = ((1LL << s) + 1LL) * a;
	double a_big = c - a;
	a_hi = c - a_big;
	a_lo = a - a_hi;
}

void mult(double a, double b,double & result, double & roundoff)
{
	result = a * b;
	std::size_t s = std::numeric_limits<double>::digits / 2 + std::numeric_limits<double>::digits % 2;
	double a_hi, a_lo, b_hi, b_lo;
	split(a, s, a_hi, a_lo);
	split(b, s, b_hi, b_lo);
	double e = result - (a_hi * b_hi) - (a_lo * b_hi) - (b_lo * a_hi);
	roundoff = (a_lo * b_lo) - e;
}

std::vector<double> add_double_to_seq(std::vector<double> seq, double f)
{
	std::size_t n = seq.size();
	std::vector<double> ans;
	for (int i = 0; i != n; ++i)
	{
		double roundoff;
		f = sum(seq[i], f, roundoff);
		ans.push_back(roundoff);
	}
	ans.push_back(f);
	return ans;
}

std::vector<double> add_pair_to_seq(std::vector<double> seq, double f1, double f2)
{
	std::vector<double> ans;
	std::vector<double> temp = add_double_to_seq(seq, f1);
	ans.push_back(temp[0]);
	std::size_t n = temp.size();
	for (int i = 1; i != n; ++i)
	{
		double roundoff;
		f2 = sum(temp[i], f2, roundoff);
		ans.push_back(roundoff);
	}
	ans.push_back(f2);
	return ans;
}

int adaptive_precision_turn(double Xa, double Ya, double Xb, double Yb, double Xc, double Yc)
{
	double greater[6];
	double lesser[6];
	mult(Xb, Yc, greater[0], lesser[0]);
	mult(-Xb, Ya, greater[1], lesser[1]);
	mult(-Xa, Yc, greater[2], lesser[2]);
	mult(-Yb, Xc, greater[3], lesser[3]);
	mult(Yb, Xa, greater[4], lesser[4]);
	mult(Ya, Xc, greater[5], lesser[5]);
	std::vector<double> result;
	result.push_back(lesser[0]);
	result.push_back(greater[0]);
	for (int i = 1; i < 6; i++)
	{
		result = add_pair_to_seq(result, lesser[i], greater[i]);
	}
	for (auto i = result.rbegin(); i != result.rend(); ++i)
	{
		if (*i > 0)
		{
			return 1;
		}
		if (*i < 0)
		{
			return -1;
		}
	}
	return 0;
}